/*!
   \file

   © 2011 Mark W. Gabby II

   This file is part of the Avion engine.

   The Avion engine is free software: you can redistribute it and/or modify it under the terms of
   the GNU General Public License as published by the Free Software Foundation, either version 3 of
   the License, or (at your option) any later version.

   The Avion engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with the Avion Engine.
   If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <vector>

#include "Math/PointN.hpp"
#include "Math/Quaternion.hpp"

#include "Components/Component.hpp"

class gcBase : public Component
{
public:
   gcBase( Entity * Owner );
   virtual bool Draw()
   {
      return false;
   }

   virtual float GetRenderIndex()
   {
      return renderIndex;
   }
   virtual void SetRenderIndex( float NewIndex )
   {
      renderIndex = NewIndex;
   }

   // Gets, sets, and moves the position of the object.
   virtual const Point3 GetPosition() const
   {
      return transform.GetPosition();
   }
   virtual const Point3 GetAbsolutePosition() const;

   virtual void SetPosition( const Point3 & NewOffset )
   {
      transform.SetPosition( NewOffset );
   }
   virtual void Translate( const Vector3 & Translation )
   {
      transform.Translate( Translation );
   }
   virtual void Translate( const float X, const float Y, const float Z )
   {
      transform.Translate( X, Y, Z );
   }

   // Gets and sets the rotation component of the object's transform.
   virtual const Matrix GetOrientation() const
   {
      return transform.GetOrientation();
   }
   virtual const Matrix GetAbsoluteOrientation() const;

   virtual void SetOrientation( const Quaternion<> & NewOffset )
   {
      transform.SetOrientation( NewOffset );
   }
   virtual void SetOrientation( const Matrix & NewOffset )
   {
      transform.SetOrientation( NewOffset );
   }

   // Gets and sets the scale offset.
   virtual const Point3 & GetScale() const
   {
      return scale;
   }
   virtual void SetScale( const Point3 & NewOffset )
   {
      scale = NewOffset;
   }
   virtual void SetScale( const float NewOffset )
   {
      scale = PointN<3>( NewOffset, NewOffset, NewOffset );
   }
   virtual void SetScale( const float X, const float Y, const float Z )
   {
      scale = PointN<3>( X, Y, Z );
   }

   /*!
      \brief
         Gets the full transform matrix.
      \note
         This matrix contains rotation and translation information, but not scale.
   */
   virtual const Matrix & GetTransform() const
   {
      return transform;
   }
   /*!
      \brief
         Sets the transform matrix.
      \note
         This matrix contains rotation and translation information, but not scale.
   */
   virtual void SetTransform( const Matrix & NewTransformOffset )
   {
      transform = NewTransformOffset;
   }

   // Gets the transformation offset, including scale information.
   virtual const Matrix GetScaledTransform() const;

   // Sets up a default modelview matrix for 3D object rendering
   virtual void SetupModelViewMatrix() const;
   virtual void RevertModelViewMatrix() const;

   uint32_t GetLastError();

   virtual ~gcBase() {}

protected:
   void SetLastError( uint32_t ErrorID )
   {
      lastErrorID = ErrorID;
   }
   void RemoveComponentFromSystem();
private:
   // Translation, orientation, and scale offsets from the entity this component
   // belongs to.
   Matrix transform;
   Point3 scale;

   // The render index is the order in which this component should be
   // rendered. Higher values are rendered first, lower values are
   // rendered last.
   float renderIndex;

   uint32_t lastErrorID;
};
